using Gtk;

namespace Ribbons {

	/**
	 * Foundation of all buttons.
	 */
	public abstract class BaseButton : Bin {

		protected Theme.ButtonState _state = Theme.ButtonState.DEFAULT;
		protected bool _is_small;

		construct { }

		/** Spacing between the content and the widget. */
		protected double _padding;
		public double padding {
			set {
				if (_padding == value) {
					return;
				}
				_padding = value;
				queue_draw ();
			}
			get { return _padding; }
		}

		/** Shape of the widget. */
		public GroupStyle group_style { get; set; }

		/** <b>true</b> if the widget should paint a background, <b>false</b> otherwise. */
		protected bool _draw_background;
		public bool draw_background {
			set {
				if (_draw_background == value) {
					return;
				}
				_draw_background = value;
				queue_draw ();
			}
			get { return _draw_background; }
		}

		protected bool _opaque_background;
		public bool opaque_background {
			set {
				if (_opaque_background == value) {
					return;
				}
				_opaque_background = value;
				queue_draw ();
			}
			get { return _opaque_background; }
		}

		/** <b>true</b> if the button is enabled, <b>false</b> otherwise. */
		protected bool _enabled;
		public bool enabled {
			set {
				if (_enabled == value) {
					return;
				}
				_enabled = value;
				queue_draw ();
			}
			get { return _enabled; }
		}

		/** Image to display. */
		protected Widget _image;
		public Widget image {
			set {
				if (_image == value) {
					return;
				}
				if (_image != null) {
					unbind_widget (_image);
				}
				_image = value;
				if (_image != null) {
					bind_widget (_image);
				}
				update_image_label ();
			}
			get { return _image; }
		}

		/** Position of the image relative to the label. */
		protected PositionType _image_position;
		public PositionType image_position {
			set {
				if (_image_position == value) {
					return;
				}
				_image_position = value;
				update_image_label ();
			}
			get { return _image_position; }
		}

		/** Label to display. */
		protected Label _label;
		public string label {
			set {
				if (_label != null) {
					unbind_widget (_label);
				}
				_label = new Label (value);
				if (_label != null) {
					bind_widget (_label);
				}
				update_image_label ();
			}
			get {
				return _label == null ? null : _label.get_text ();
			}
		}

		/** Theme used to draw the widget. */
		protected Theme _theme = new Theme ();
		public Theme theme {
			set {
				_theme = value;
				queue_draw ();
			}
			get { return _theme; }
		}

		/** Binds a widget to listen to all button events. */
		private void bind_widget (Widget w) {
			w.button_press_event.connect (bound_widget_button_press_event);
			w.button_release_event.connect (bound_widget_button_release_event);
		}

		/** Unbinds a widget to no longer listen to button events. */
		private void unbind_widget (Widget w) {
			w.button_press_event.disconnect (bound_widget_button_press_event);
			w.button_release_event.disconnect (bound_widget_button_release_event);
		}

		/** Called when a mouse button has been pressed on a binded widget. */
		protected abstract bool bound_widget_button_press_event (Widget sender,
														Gdk.EventButton event);

		/** Called when a mouse button has been release on a binded widget. */
		protected abstract bool bound_widget_button_release_event (Widget sender,
														Gdk.EventButton event);

		/** Updates the child widget containing the label and/or image. */
		private void update_image_label () {
			if (this.child != null) {
				var con = this.child as Container;
				if (con != null) {
					con.remove (_image);
					con.remove (_label);
				}
				remove (this.child);
			}

			if (_label != null && _image != null) {
				switch (_image_position) {
				case PositionType.TOP:
					{
						var box = new VBox (false, 0);
						box.add (_image);
						box.add (_label);
						add (box);
						break;
					}
				case PositionType.BOTTOM:
					{
						var box = new VBox (false, 0);
						box.add (_label);
						box.add (_image);
						add (box);
						break;
					}
				case PositionType.LEFT:
					{
						var box = new HBox (false, 0);
						box.add (_image);
						box.add (_label);
						add (box);
						break;
					}
				case PositionType.RIGHT:
					{
						var box = new HBox (false, 0);
						box.add (_label);
						box.add (_image);
						add (box);
						break;
					}
				}
			}	else if (_label != null) {
				add (_label);
			} else if (_image != null) {
				add (_image);
			}
		}
	}
}
